package sum.book.auth.server.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.*;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Arrays;

/**
 * @Auther: ZhangGN
 * @Description: Token的存储策略
 * @Date 2022/11/21 16:53
 **/
@Configuration
public class BeanConfig {

    String PROJECT_OAUTH_ACCESS = "book:access:";

    @Resource
    DataSource dataSource;


    @Resource
    RedisConnectionFactory redisConnectionFactory;


    @Bean
    public HeaderValueFilter headerValueFilter() {
        return new HeaderValueFilter();
    }


    @Bean
    public TokenStore tokenStore() {
        RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
        redisTokenStore.setPrefix(PROJECT_OAUTH_ACCESS);
        return redisTokenStore;
    }


    /**
     * 配置token的生成
     *
     * @return
     */
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("BookSecret"); //对称秘钥，资源服务器使用该秘钥来验证
        return converter;
    }


    /**
     * 自定义 TokenService
     *
     * @return
     */
    @Bean
    public AuthorizationServerTokenServices customAuthorizationServerTokenServices() {
        DefaultTokenServices service = new DefaultTokenServices();

        // TokenStore
        service.setTokenStore(tokenStore());//令牌存储策略

        // jwt令牌转换器(令牌增强)
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        //tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer, customAccessTokenConverter()));

        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter()));
        service.setTokenEnhancer(tokenEnhancerChain);

        // 其他
        service.setSupportRefreshToken(true); // 支持刷新令牌
        service.setAccessTokenValiditySeconds(7200);
        service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天

        return service;
    }


    /**
     * 自定义ClientDetails
     *
     * @return
     */
    @Bean
    public ClientDetailsService customClientDetailsService() {
        // Spring Security OAuth2 架构上分为Authorization Server认证服务器和Resource Server资源服务器。
        // 我们可以为每一个Resource Server（一个微服务实例）设置一个resourceId。
        // Authorization Server给client第三方客户端授权的时候，可以设置这个client可以访问哪一些Resource Server资源服务，
        // 如果没设置，就是对所有的Resource Server都有访问权限
        return new JdbcClientDetailsService(dataSource);
    }
}


